package com.apobates.forum.orize;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 抽像的执行器/负责具体的验证工作.要求是单例的
 * @author xiaofanku@live.cn
 * @since 20210822
 */
public abstract class OrizeExecutor {
    private final static Logger logger = LoggerFactory.getLogger(OrizeExecutor.class);
    private final static String NEWLINE = "\r\n";

    //2: 将XML结构的资源文档转成方便查询的可缓存树
    //ETC

    /**
     * 3: 执行搜索
     * @param expression 请求信息表达式
     * @return
     * @throws MalformedURLException
     */
    public OrizeMatchResult match(final OrizeExpression expression) throws MalformedURLException {
        //final OrizeMatchResult.Builder builder = new OrizeMatchResult.Builder(expression);
        //3.1 生成xpath表达式
        //是否包含查询字符串
        String[] tmp = extractURL(expression.path());
        if(tmp.length == 0){
            return new OrizeMatchResult.Builder(expression).error("请求地址解析失败");
        }
        final String _reqPath = tmp[0];
        final String _reqQueryStr=tmp[1];
        final String _reqMethod = expression.method();
        //3.2 搜索需要验证的资源
        CompletableFuture<OrizeMatchResult> strictMatchTask = CompletableFuture.supplyAsync(() ->strictMatch(_reqPath,_reqQueryStr,_reqMethod, expression));
        CompletableFuture<OrizeMatchResult> slotMatchTask = CompletableFuture.supplyAsync(() ->slotMatch(_reqPath,_reqQueryStr,_reqMethod, expression));
        try{
            OrizeMatchResult omr = strictMatchTask.thenCombine(slotMatchTask, (stmt, slmt)->{
                return Optional.ofNullable(stmt).orElse(slmt);
            }).get();
            return Optional.ofNullable(omr).orElse(new OrizeMatchResult.Builder(expression).pass());
        }catch (InterruptedException | ExecutionException e){
            return new OrizeMatchResult.Builder(expression).error(e.getMessage());
        }
    }

    /**
     * 严格全模式匹配
     * @param reqPath 请求路径
     * @param reqQueryString 请求地址中的查询参数
     * @param reqMethod 请求方法
     * @param expression 请求信息表达式
     * @return
     */
    protected abstract OrizeMatchResult strictMatch(String reqPath, String reqQueryString, String reqMethod, OrizeExpression expression);

    /**
     * 占位符全模式匹配
     * @param reqPath 请求路径
     * @param reqQueryString 请求地址中的查询参数
     * @param reqMethod 请求方法
     * @param expression 请求信息表达式
     * @return
     */
    protected abstract OrizeMatchResult slotMatch(String reqPath, String reqQueryString, String reqMethod, OrizeExpression expression);


    public void destroy(){
    }

    /**
     * 提取请求地址中的路径和查询字符串
     * @param reqUrl 请求地址
     * @return 0=路径,1=查询字符串
     * @throws MalformedURLException
     */
    protected static String[] extractURL(String reqUrl) throws MalformedURLException {
        if(null == reqUrl || reqUrl.isEmpty()){
            return new String[0];
        }
        String tmp = reqUrl;
        if(!reqUrl.startsWith("http")){
            tmp = "http://localhost";
            if(!reqUrl.startsWith("/")){
                tmp += "/";
            }
            tmp += reqUrl;
        }
        URL url = new URL(tmp);
        return new String[]{url.getPath(), url.getQuery()};
    }

}
